
from django.contrib.auth.models import AbstractUser
import secrets
from django.db import models
from django.utils import timezone




class User(AbstractUser):
    ROLE_CHOICES = (
        ('customer', '顾客'),
        ('producer', '生产商'),
        ('admin', '管理员'),
    )

    role = models.CharField(max_length=10, choices=ROLE_CHOICES, default='customer')
    phone = models.CharField(max_length=15, blank=True, null=True)

    # 解决反向关系冲突
    groups = models.ManyToManyField(
        'auth.Group',
        verbose_name='groups',
        blank=True,
        help_text='The groups this user belongs to.',
        related_name='data_app_users',
        related_query_name='data_app_user',
    )

    user_permissions = models.ManyToManyField(
        'auth.Permission',
        verbose_name='user permissions',
        blank=True,
        help_text='Specific permissions for this user.',
        related_name='data_app_users',
        related_query_name='data_app_user',
    )

    def is_customer(self):
        return self.role == 'customer'

    def is_producer(self):
        return self.role == 'producer'

    def is_admin(self):
        return self.role == 'admin'


# encryption/models.py
from django.db import models
from django.conf import settings


class UserKeyPair(models.Model):
    """用户ECC密钥对"""
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='key_pair')
    public_key = models.TextField()  # PEM格式公钥
    private_key = models.TextField()  # PEM格式私钥（无加密存储）
    created_at = models.DateTimeField(auto_now_add=True)

    def generate_keys(self):
        """生成ECDSA密钥对（SECP256R1曲线）"""
        private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
        public_key = private_key.public_key()

        # 序列化公钥
        public_pem = public_key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        ).decode('utf-8')

        # 序列化私钥（不加密）
        private_pem = private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption()
        ).decode('utf-8')

        self.public_key = public_pem
        self.private_key = private_pem
        self.save()
        return private_key, public_key

    @classmethod
    def get_or_create_key_pair(cls, user):
        """获取或创建用户密钥对"""
        key_pair, created = cls.objects.get_or_create(user=user)
        if created or not key_pair.public_key:
            key_pair.generate_keys()
        return key_pair


from django.db import models
from django.conf import settings
import uuid
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.exceptions import InvalidSignature
import base64
import os

class AgriculturalProduct(models.Model):
    #产品名称
    product_name = models.CharField(max_length=100, verbose_name='产品名称')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    raw_material_source = models.TextField(verbose_name='原材料来源')
    production_process = models.TextField(verbose_name='生产过程')
    inspection_batch = models.CharField(max_length=100, verbose_name='检验批次')
    logistics_flow = models.TextField(verbose_name='物流流转')
    anti_counterfeiting_certification = models.TextField(verbose_name='防伪鉴证')
    created_at = models.DateTimeField(auto_now_add=True)
    is_listed = models.BooleanField(default=False, verbose_name='是否上架')
    listed_at = models.DateTimeField(null=True, blank=True, verbose_name='上架时间')
    # 新增字段：图片上传
    product_image = models.ImageField(upload_to='product_images/', null=True, blank=True)  # 图片存储路径

    # 新增金额字段
    price = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        verbose_name='商品价格',
        default=0.00
    )
    # 新增字段：是否已售出
    is_sold = models.BooleanField(
        default=False,
        verbose_name='是否已售出'
    )

    sold_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='售出时间'
    )
    def upload_to(instance, filename):
        base_filename, file_extension = os.path.splitext(filename)
        return f'product_images/{uuid.uuid4()}{file_extension}'
    def __str__(self):
        return f"Product by {self.user.username} at {self.created_at}"



class EncryptedData(models.Model):
    """加密数据包"""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='encrypted_data'
    )
    encrypted_aes_key = models.TextField()  # ECC加密的AES密钥（Base64编码）
    encrypted_data = models.TextField()     # AES加密的数据（Base64编码，包含IV和Tag）
    signature = models.TextField()          # 数据签名（Base64编码）
    data_hash = models.TextField()          # 数据哈希（Base64编码）
    created_at = models.DateTimeField(auto_now_add=True)
    sender_public_key = models.TextField(null=True, blank=True)
    agricultural_product = models.ForeignKey(
        AgriculturalProduct,
        on_delete=models.CASCADE,
        null=True,
        blank=True
    )

    def encrypt_data(self, plaintext, user):
        key_pair = UserKeyPair.get_or_create_key_pair(user)
        private_key_pem = key_pair.private_key
        public_key_pem = key_pair.public_key

        # 载入私钥和公钥
        private_key = serialization.load_pem_private_key(
            private_key_pem.encode('utf-8'),
            password=None,
            backend=default_backend()
        )
        public_key = serialization.load_pem_public_key(
            public_key_pem.encode('utf-8'),
            backend=default_backend()
        )

        # 生成随机 AES 密钥
        aes_key = secrets.token_bytes(32)

        # 使用 ECDH 生成共享密钥，用于包装 AES 密钥
        shared_key_for_wrapping = private_key.exchange(ec.ECDH(), public_key)
        wrapping_key = HKDF(
            algorithm=hashes.SHA256(),
            length=32,
            salt=None,
            info=b'aes-key-wrapping',
            backend=default_backend()
        ).derive(shared_key_for_wrapping)

        # 简单 XOR 实现 AES 密钥加密（示例：应使用标准算法如 AES-WRAP）
        wrapped_aes_key = bytes(a ^ b for a, b in zip(aes_key, wrapping_key))
        self.encrypted_aes_key = base64.b64encode(wrapped_aes_key).decode('utf-8')

        # AES-GCM 加密主数据
        iv = os.urandom(16)
        cipher = Cipher(algorithms.AES(aes_key), modes.GCM(iv), backend=default_backend())
        encryptor = cipher.encryptor()
        ciphertext = encryptor.update(plaintext.encode('utf-8')) + encryptor.finalize()
        tag = encryptor.tag

        encrypted_content = iv + tag + ciphertext
        self.encrypted_data = base64.b64encode(encrypted_content).decode('utf-8')

        # 计算哈希 & 签名
        digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
        digest.update(ciphertext)
        data_hash = digest.finalize()
        self.data_hash = base64.b64encode(data_hash).decode('utf-8')

        signature = private_key.sign(data_hash, ec.ECDSA(hashes.SHA256()))
        self.signature = base64.b64encode(signature).decode('utf-8')

        self.sender_public_key = public_key_pem
        self.user = user
        self.save()

        return self


    def decrypt(self):
        user = self.user
        key_pair = UserKeyPair.objects.get(user=user)
        private_key_pem = key_pair.private_key
        private_key = serialization.load_pem_private_key(
            private_key_pem.encode('utf-8'),
            password=None,
            backend=default_backend()
        )

        sender_public_key = serialization.load_pem_public_key(
            self.sender_public_key.encode('utf-8'),
            backend=default_backend()
        )

        # 重新生成包装密钥
        shared_key_for_wrapping = private_key.exchange(ec.ECDH(), sender_public_key)
        wrapping_key = HKDF(
            algorithm=hashes.SHA256(),
            length=32,
            salt=None,
            info=b'aes-key-wrapping',
            backend=default_backend()
        ).derive(shared_key_for_wrapping)

        # 解封 AES 密钥
        wrapped_aes_key = base64.b64decode(self.encrypted_aes_key)
        aes_key = bytes(a ^ b for a, b in zip(wrapped_aes_key, wrapping_key))

        # 解密主数据
        decoded_data = base64.b64decode(self.encrypted_data)
        iv = decoded_data[:16]
        tag = decoded_data[16:32]
        ciphertext = decoded_data[32:]

        cipher = Cipher(algorithms.AES(aes_key), modes.GCM(iv, tag), backend=default_backend())
        decryptor = cipher.decryptor()
        decrypted_bytes = decryptor.update(ciphertext) + decryptor.finalize()

        return decrypted_bytes.decode('utf-8')


class UserActivityLog(models.Model):
    ACTION_CHOICES = (
        ('login', '登录'),
        ('logout', '登出'),
        ('text_encrypt', '文本加密'),
        ('view_history', '查看历史记录'),
        ('view_detail', '查看详情'),
        ('input_data', '录入农产品信息'),
        ('agricultural_product_list', '查询农产品列表'),
        ('decrypt', '解密数据'),
        ('product_sell', '获取商品列表'),
        ('sell_product', '商品上架'),
        ('product_catalog', '查看商品目录'),
        ('place_order', '下单'),
        ('order_history_view', '查看订单历史'),
        ('cancel_order', '取消订单'),
        ('toggle_product_listing', '切换商品上架状态'),
        ('edit_agricultural_product', '编辑商品'),
        ('sold_orders_all', '查看所有订单'),
        ('order_details', '查看订单详情'),
    )

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='activity_logs'
    )
    action = models.CharField(max_length=50, choices=ACTION_CHOICES)
    description = models.TextField(blank=True, null=True)
    ip_address = models.GenericIPAddressField(null=True, blank=True)
    user_agent = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return f"{self.user.username} - {self.get_action_display()} - {self.created_at}"

class CustomerProfile(models.Model):
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        limit_choices_to={'role': 'customer'},
        related_name='customer_profile'
    )
    address = models.TextField(blank=True, null=True, verbose_name='地址')
    company = models.CharField(max_length=100, blank=True, null=True, verbose_name='公司名称')


class ProducerProfile(models.Model):
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        limit_choices_to={'role': 'producer'},
        related_name='producer_profile'
    )
    business_license = models.CharField(max_length=100, verbose_name="营业执照编号")
    company_name = models.CharField(max_length=100, verbose_name="企业名称")

class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product = models.ForeignKey(AgriculturalProduct, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    shipping_address = models.TextField(verbose_name='收货地址', blank=True, null=True)
    quantity = models.PositiveIntegerField(default=1, verbose_name='数量')
    STATUS_CHOICES = (
        ('pending', '已下单'),
        ('paid', '已支付'),
        ('shipped', '已发货'),
        ('cancelled', '已取消'),  # 新增取消状态
    )

    status = models.CharField(
        max_length=20,
        default='pending',
        choices=STATUS_CHOICES,
        verbose_name='状态'
    )
    def get_status_display(self):
        status_dict = {
            'pending': '已下单',
            'paid': '已支付',
            'shipped': '已发货',
            'cancelled': '已取消',  # 新增取消状态
        }
        return status_dict.get( self.status)





